import os
import random
import json
import time


class BaseAccount:
    """账户基类 - 展示继承的基础"""

    def __init__(self, account_id, owner_name):
        self._account_id = account_id  # 封装：使用下划线表示私有属性
        self._owner_name = owner_name
        self._balance = 0.0
        self._status = 'active'  # active or locked

    @property
    def account_id(self):
        """获取账号 - 封装：属性访问器"""
        return self._account_id

    @property
    def owner_name(self):
        """获取账户所有者姓名 - 封装：属性访问器"""
        return self._owner_name

    @property
    def balance(self):
        """获取账户余额 - 封装：属性访问器"""
        return self._balance

    @property
    def status(self):
        """获取账户状态 - 封装：属性访问器"""
        return self._status

    def deposit(self, amount):
        """存款方法 - 多态的基础"""
        if self._status != 'active':
            raise ValueError("账户已被锁定，无法存款")
        if amount <= 0:
            raise ValueError("存款金额必须大于0")
        self._balance += amount
        return self._balance

    def withdraw(self, amount):
        """取款方法 - 多态的基础"""
        if self._status != 'active':
            raise ValueError("账户已被锁定，无法取款")
        if amount <= 0:
            raise ValueError("取款金额必须大于0")
        if amount > self._balance:
            raise ValueError("余额不足")
        self._balance -= amount
        return self._balance

    def lock(self):
        """锁定账户"""
        self._status = 'locked'

    def unlock(self):
        """解锁账户"""
        self._status = 'active'

    def to_dict(self):
        """将账户信息转换为字典格式，便于序列化"""
        return {
            'account_id': self._account_id,
            'owner_name': self._owner_name,
            'balance': self._balance,
            'status': self._status
        }


class BankAccount(BaseAccount):
    """银行账户类 - 继承BaseAccount"""

    def __init__(self, account_id, owner_name, id_card, phone, password):
        super().__init__(account_id, owner_name)
        self._id_card = id_card
        self._phone = phone
        self._password = password
        self._wrong_password_count = 0

    def verify_password(self, password):
        """验证密码"""
        if password == self._password:
            self._wrong_password_count = 0
            return True
        else:
            self._wrong_password_count += 1
            if self._wrong_password_count >= 3:
                self.lock()
                raise ValueError("密码错误次数过多，账户已被锁定")
            return False

    def change_password(self, old_password, new_password):
        """修改密码"""
        if not self.verify_password(old_password):
            raise ValueError("原密码错误")
        self._password = new_password
        return True

    def to_dict(self):
        """扩展父类的to_dict方法"""
        data = super().to_dict()
        data.update({
            'id_card': self._id_card,
            'phone': self._phone,
            'password': self._password,
            'wrong_password_count': self._wrong_password_count
        })
        return data


class AccountFactory:
    """账户工厂类 - 展示工厂设计模式"""

    @staticmethod
    def create_bank_account(owner_name, id_card, phone, password, initial_balance=0.0):
        """创建银行账户"""
        account_id = AccountFactory.generate_account_id()
        account = BankAccount(account_id, owner_name, id_card, phone, password)
        if initial_balance > 0:
            account.deposit(initial_balance)
        return account

    @staticmethod
    def generate_account_id():
        """生成唯一的账号"""
        return ''.join(random.choices('0123456789', k=6))


class DataStorage:
    """数据存储类 - 单一职责原则"""

    def __init__(self, file_path):
        self._file_path = file_path

    def load_data(self):
        """加载数据"""
        if os.path.exists(self._file_path):
            try:
                with open(self._file_path, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except:
                return {}
        return {}

    def save_data(self, data):
        """保存数据"""
        try:
            os.makedirs(os.path.dirname(self._file_path), exist_ok=True)
            with open(self._file_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=4)
            return True
        except:
            return False


class BankTransaction:
    """银行交易类 - 处理各类交易"""

    @staticmethod
    def transfer(from_account, to_account, amount, password):
        """转账操作"""
        # 验证转出账户密码
        if not from_account.verify_password(password):
            raise ValueError("密码错误")

        # 检查是否是自转账
        if from_account.account_id == to_account.account_id:
            raise ValueError("不能向自己转账")

        # 执行转账
        from_account.withdraw(amount)
        to_account.deposit(amount)
        return True
